package jdklearning.classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;


/**
 * http://blog.csdn.net/turkeyzhou/article/details/2792876
 *
 * 放置到< Java_Runtime_Home >/lib目录下的TestBean对应的class字节码并没有被加载，
 * 这其实和前面讲的双亲委派机制并不矛盾。 虚拟机出于安全等因素考虑，不会加载< Java_Runtime_Home >/lib存在的陌生类，
 * 开发者通过将要加载的非JDK自身的类放置到此目录下期待启动类加载器加载是不可能的。
 **/
public class ClassLoaderLearning {

	// 技巧,定位资源
	public static void loadResource() {
		String path1 = Thread.currentThread().getContextClassLoader().getResource("").getPath();
		// ClassLoaderLearning.class.getClassLoader().getResourceAsStream("");
		// ClassLoaderLearning.class.getClassLoader().getResource("");

		System.out.println(path1);
	}

	public static void classLoaderPath() {
		System.out.println("sun.boot.class.path: "+System.getProperty("sun.boot.class.path"));
		System.out.println("java.ext.dirs: "+System.getProperty("java.ext.dirs"));
		System.out.println("java.class.path: "+System.getProperty("java.class.path"));
		System.out.println("user.dir: "+System.getenv("user.dir"));
		System.out.println(ClassLoaderLearning.class.getClassLoader());
		System.out.println(ClassLoaderLearning.class.getClassLoader().getParent());
		System.out.println(ClassLoaderLearning.class.getClassLoader().getParent().getParent());
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// classLoaderPath();
		
		System.out.println("java.ext.dirs: "+System.getProperty("java.ext.dirs"));
		
		try {
			Class clazz = Class.forName("com.mysql.jdbc.Driver", true, new MyClassLoader());// 双亲委派
			System.out.println(clazz.getClassLoader());
			Class clazz1 = Class.forName("jdklearning.classloader.test.A", true, new MyClassLoader());// 双亲委派
			System.out.println(clazz1.getClassLoader());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
//		System.out.println("jdklearning.classloader.test.A".substring(0, "jdklearning.classloader.test.A".lastIndexOf('.')));
//		
//		String classDir = "/classes";
//		String name = "jdklearning.classloader.test.A";
//		String temp1 = name.substring(0, name.lastIndexOf('.'));
//		String[] temp2 = temp1.split("\\.");  注意转义
//		String temp3 = String.join(File.separator, temp2);
//		
//		String classFileName = classDir + File.separator + temp3 + ".class";
//		System.out.println(classFileName);
	}





	static class MyClassLoader extends ClassLoader {

		private static String classDir = "/classes";

		public MyClassLoader() {
			super();
			// TODO Auto-generated constructor stub
		}

		private static void cypher(InputStream ips, OutputStream ops) throws Exception {
			int b = -1;
			while ((b = ips.read()) != -1) {
//			System.out.println(b);
//			System.out.println(b & 0xffffffff);
//			System.out.println(0xffffffff);

				ops.write(b & 0xffffffff);
			}
		}

		@Override
		protected Class<?> findClass(String name) throws ClassNotFoundException {
			String destDir = String.join(File.separator, name.substring(0, name.lastIndexOf('.')).split("\\."));
			String classFileName = classDir + File.separator + destDir + File.separator + name.substring(name.lastIndexOf('.') + 1) + ".class";

			try {
				FileInputStream fis = new FileInputStream(classFileName);
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				cypher(fis, bos);
				fis.close();
				byte[] bytes = bos.toByteArray();
				return defineClass(name, bytes, 0, bytes.length);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}

	}

}


